package com.fattyCorps.game.service;

import com.fattyCorps.common.mgr.Cfg;
import com.fattyCorps.common.mgr.GlobalConfig;
import com.fattyCorps.common.obj.config.ItemMould;
import com.fattyCorps.common.obj.dto.DItemConsume;
import com.fattyCorps.common.packet.dto.DItem;
import com.fattyCorps.game.service.player.PlayerService;
import com.fattyCorps.game.an.AEventListener;
import com.fattyCorps.game.cache.PlayerCache;
import com.fattyCorps.common.packet.PacketMap;
import com.fattyCorps.game.exception.game.item.ItemCanNotUseErrorException;
import com.fattyCorps.game.exception.game.item.ItemIdErrorException;
import com.fattyCorps.game.exception.game.item.ItemNotEnoughErrorException;
import com.fattyCorps.game.exception.game.item.ItemNumErrorException;
import com.fattyCorps.game.mgr.event.EEvent;
import com.fattyCorps.game.obj.cache.PlayerInfo;
import com.fattyCorps.common.packet.Item;
import com.fattyCorps.game.obj.msg.SRet;
import com.fattyCorps.game.obj.msg.server.item.SGetItemListMsg;
import com.fattyCorps.game.obj.msg.server.item.SSaleItemMsg;
import com.fattyCorps.game.obj.msg.server.item.SUseItemMsg;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;

@Service
@Slf4j
public class ItemService {

    @Autowired
    PlayerCache playerCache;

    @Autowired
    Cfg cfg;

    @Autowired
    HeroService heroService;

    @Autowired
    PlayerService playerService;

    @Autowired
    GlobalConfig globalConfig;

    // 创建角色时初始化用户身上的道具
    @AEventListener(EEvent.EVENT_ON_PLAYER_CREATE)
    public void onPlayerCreate(PlayerInfo playerInfo) {
        String initItemsStr = globalConfig.getStringValue(GlobalConfig.PLAYER_INIT_ITEMS);
        String[] split = initItemsStr.split(",");

        for (int i = 0; i < split.length; i++) {
            Integer itemTypeID = Integer.valueOf(split[i]);
            i = i + 1;
            Integer itemNum = Integer.valueOf(split[i]);

            // 增加道具
            Item item = Item.makeItem(itemTypeID, itemNum);
            playerInfo.getPlayerData().getItems().put(item);
        }
    }

    // 获取道具列表
    public SRet getItemList(Integer playerId) {
        PlayerInfo playerInfo = playerCache.getPlayerInfo(playerId);
        List<Item> items = playerInfo.getPlayerData().getItems().getElems();
        SGetItemListMsg sGetItemListMsg = new SGetItemListMsg();
        sGetItemListMsg.setItemList(items);
        return SRet.success(sGetItemListMsg);
    }

    // 使用道具
    public SRet useItem(Integer playerId, Integer itemId, Integer num) {
        if (num <= 0) {
            throw new ItemNumErrorException();
        }

        Item item = getItem(playerId, itemId);
        if (item == null) {
            throw new ItemIdErrorException();
        }

        ItemMould itemMould = cfg.getCfg(ItemMould.class, item.getTypeId());

        if (!itemMould.getSubType().isUseable()) {
            throw new ItemCanNotUseErrorException();
        }

        switch (itemMould.getSubType()) {
            case HeroFragment: {
                // 英雄碎片
                Integer heroTypeId = Integer.valueOf(itemMould.getProp());
                Integer oneHeroFragmentNum = globalConfig.getIntValue(GlobalConfig.ONE_HERO_FRAGMENT_NUM);
                if (num % oneHeroFragmentNum != 0) {
                    throw new ItemNumErrorException();
                }
                int heroNum = num / oneHeroFragmentNum;

                // 删除道具
                boolean b = delItem(item, num);
                if (b) {
                    // 创建英雄
                    for (int i = 0; i < heroNum; i++) {
                        heroService.createHero(playerId, heroTypeId);
                    }
                } else {
                    // 道具数量不足
                    throw new ItemNotEnoughErrorException();
                }
                break;
            }
            case Coin: {
                // 元宝
                Integer coinNum = Integer.valueOf(itemMould.getProp());
                // 删除道具
                boolean b = delItem(item, num);
                if (b) {
                    playerService.addCoin(playerId, coinNum * num);
                } else {
                    // 道具数量不足
                    throw new ItemNotEnoughErrorException();
                }
                break;
            }
            case IdlePrice: {
                // 挂机奖励
                // todo: 等关卡模块实现后来做
                throw new RuntimeException("暂不支持的道具子类型");
            }
            default:
                // 普通道具
                throw new ItemCanNotUseErrorException();
        }

        // 返回道具最新的数量
        SUseItemMsg sUseItemMsg = new SUseItemMsg();
        sUseItemMsg.setNewNum(item.getNum());
        return SRet.success(sUseItemMsg);
    }

    public SRet saleItem(Integer playerId, Integer itemId, Integer num) {
        if (num <= 0) {
            throw new ItemNumErrorException();
        }

        Item item = getItem(playerId, itemId);
        if (item == null) {
            throw new ItemIdErrorException();
        }

        ItemMould itemMould = cfg.getCfg(ItemMould.class, item.getTypeId());

        // 删除道具
        boolean b = delItem(item, num);
        if (b) {
            playerService.addMoney(playerId, itemMould.getSaleMoney() * num);
        } else {
            // 道具数量不足
            throw new ItemNotEnoughErrorException();
        }

        SSaleItemMsg msg = new SSaleItemMsg();
        msg.setNewNum(item.getNum());
        return SRet.success(msg);
    }

    // 创建道具
    public void addItem(Integer playerId, Integer itemTypeId, Integer num) {
        Item item = getItemByTypeId(playerId, itemTypeId, false);
        if (item == null) {
            // 用户身上没有该typeId的道具
            Item newItem = Item.makeItem(itemTypeId, num);

            // 再去内存中增加
            getPacketItem(playerId).put(newItem);
        } else {
            // 用户身上有该typeId的道具
            Integer newNum = item.getNum() + num;
            item.setNum(newNum);
            getPacketItem(playerId).put(item);
        }
    }

    public void addItemBatch(Integer playerId, List<DItem> items) {
        for (DItem item : items) {
            addItem(playerId, item.getTypeId(), item.getNum());
        }
    }

    // 批量删除道具
    public boolean delItemBatch(Integer playerId, List<DItemConsume> dItems) {
        for (DItemConsume dItem : dItems) {
            Item item = getItemByTypeId(playerId, dItem.getTypeId());
            if (item.getNum() < dItem.getNum()) {
                return false;
            }
        }

        for (DItemConsume dItem : dItems) {
            delItemByTypeId(playerId, dItem.getTypeId(), dItem.getNum());
        }

        return true;
    }

    // 根据道具typeId删除道具
    public boolean delItemByTypeId(Integer playerId, Integer itemTypeId, Integer delNum) {
        Item item = getItemByTypeId(playerId, itemTypeId);
        return delItem(item, delNum);
    }

    // 删除道具
    public boolean delItem(Integer playerId, Integer itemId, Integer delNum) {
        Item item = getItem(playerId, itemId);
        return delItem(item, delNum);
    }

    // 删除道具
    public boolean delItem(Item item, Integer delNum) {
        if (item.getNum() < delNum) {
            // 道具数量不足
            return false;
        } else {
            int newNum = item.getNum() - delNum;
            item.setNum(newNum);
        }
        return true;
    }

    // 根据道具id获取道具信息
    public Item getItem(Integer playerId, Integer itemId) {
        return getPacketItem(playerId).get(itemId);
    }

    // 根据道具typeId获取道具信息
    public Item getItemByTypeId(Integer playerId, Integer itemTypeId) {
        return getItemByTypeId(playerId, itemTypeId, true);
    }

    public Item getItemByTypeId(Integer playerId, Integer itemTypeId, boolean t) {
        List<Item> items = getPacketItem(playerId).getElems();
        for (int i = 0; i < items.size(); i++) {
            Item item = items.get(i);
            if (item.getTypeId().equals(itemTypeId)) {
                return item;
            }
        }

        if (t) {
            throw new ItemNotEnoughErrorException();
        }

        return null;
    }

    public PacketMap<Item> getPacketItem(Integer playerId) {
        return playerCache.getPlayerInfo(playerId).getPlayerData().getItems();
    }
}
